package com.kaizeli.website.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.kaizeli.website.pojo.dto.ProjectExcelDTO;
import com.kaizeli.website.service.ProjectImportService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 项目导入服务实现类
 */
@Slf4j
@Service
public class ProjectImportServiceImpl implements ProjectImportService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 导入Excel文件到project表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> importProjectExcel(MultipartFile file, boolean updateIfExists) {
        Map<String, Object> result = new HashMap<>();
        
        // 校验文件
        if (file == null || file.isEmpty()) {
            result.put("success", false);
            result.put("message", "文件为空，请上传Excel文件");
            return result;
        }

        String filename = file.getOriginalFilename();
        if (filename == null || (!filename.endsWith(".xlsx") && !filename.endsWith(".xls"))) {
            result.put("success", false);
            result.put("message", "文件格式错误，仅支持Excel文件（.xlsx或.xls）");
            return result;
        }

        // 用于统计
        final int[] successCount = {0};
        final int[] updateCount = {0};
        final int[] failCount = {0};
        final List<String> errorMessages = new ArrayList<>();
        final Set<String> existingCodes = new HashSet<>();
        
        log.info("开始导入Excel，更新模式：{}", updateIfExists ? "存在则更新" : "存在则跳过");

        try (InputStream inputStream = file.getInputStream()) {
            // 使用EasyExcel读取文件
            EasyExcel.read(inputStream, ProjectExcelDTO.class, new ReadListener<ProjectExcelDTO>() {
                
                @Override
                public void invoke(ProjectExcelDTO data, AnalysisContext context) {
                    Integer rowNum = context.readRowHolder().getRowIndex() + 1; // Excel行号（从1开始）
                    
                    try {
                        // 数据校验
                        String validationError = validateProjectData(data, rowNum);
                        if (validationError != null) {
                            errorMessages.add(validationError);
                            failCount[0]++;
                            return;
                        }

                        // 检查项目编码是否已存在
                        if (existingCodes.contains(data.getProjectCode())) {
                            errorMessages.add(String.format("第%d行：项目编码 [%s] 在Excel中重复", rowNum, data.getProjectCode()));
                            failCount[0]++;
                            return;
                        }

                        // 检查数据库中是否已存在该项目编码
                        String checkSql = "SELECT COUNT(*) FROM project WHERE project_code = ? AND is_deleted = 0";
                        Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, data.getProjectCode());
                        boolean exists = (count != null && count > 0);
                        
                        if (exists) {
                            if (updateIfExists) {
                                // 更新模式：更新已存在的项目
                                String updateSql = "UPDATE project SET " +
                                        "project_name = ?, " +
                                        "description = ?, " +
                                        "status = ?, " +
                                        "priority = ?, " +
                                        "start_date = ?, " +
                                        "end_date = ?, " +
                                        "budget = ?, " +
                                        "estimated_cost_rate = ?, " +
                                        "project_type = ?, " +
                                        "progress = ?, " +
                                        "is_public = ?, " +
                                        "update_time = NOW() " +
                                        "WHERE project_code = ? AND is_deleted = 0";

                                jdbcTemplate.update(updateSql,
                                        data.getProjectName(),
                                        data.getDescription(),
                                        data.getStatus() != null ? data.getStatus() : 1,
                                        data.getPriority() != null ? data.getPriority() : 3,
                                        data.getStartDate(),
                                        data.getEndDate(),
                                        data.getBudget(),
                                        data.getEstimatedCostRate(),
                                        data.getProjectType(),
                                        data.getProgress() != null ? data.getProgress() : 0,
                                        data.getIsPublic() != null ? data.getIsPublic() : 0,
                                        data.getProjectCode()
                                );

                                updateCount[0]++;
                                log.info("成功更新项目：{} - {}", data.getProjectCode(), data.getProjectName());
                            } else {
                                // 跳过模式：项目已存在，跳过
                                errorMessages.add(String.format("第%d行：项目编码 [%s] 已存在于数据库中（跳过）", 
                                    rowNum, data.getProjectCode()));
                                failCount[0]++;
                                return;
                            }
                        } else {
                            // 插入新数据
                            String insertSql = "INSERT INTO project (project_code, project_name, description, status, priority, " +
                                    "start_date, end_date, budget, estimated_cost_rate, project_type, progress, is_public, " +
                                    "create_time, update_time, is_deleted) " +
                                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW(), 0)";

                            jdbcTemplate.update(insertSql,
                                    data.getProjectCode(),
                                    data.getProjectName(),
                                    data.getDescription(),
                                    data.getStatus() != null ? data.getStatus() : 1,
                                    data.getPriority() != null ? data.getPriority() : 3,
                                    data.getStartDate(),
                                    data.getEndDate(),
                                    data.getBudget(),
                                    data.getEstimatedCostRate(),
                                    data.getProjectType(),
                                    data.getProgress() != null ? data.getProgress() : 0,
                                    data.getIsPublic() != null ? data.getIsPublic() : 0
                            );

                            successCount[0]++;
                            log.info("成功新增项目：{} - {}", data.getProjectCode(), data.getProjectName());
                        }

                        existingCodes.add(data.getProjectCode());

                    } catch (Exception e) {
                        log.error("导入第{}行数据失败：{}", rowNum, e.getMessage(), e);
                        errorMessages.add(String.format("第%d行：导入失败 - %s", rowNum, e.getMessage()));
                        failCount[0]++;
                    }
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    log.info("Excel文件读取完成，新增：{}条，更新：{}条，失败：{}条", 
                        successCount[0], updateCount[0], failCount[0]);
                }
            }).sheet().doRead();

            // 返回结果
            int totalSuccess = successCount[0] + updateCount[0];
            String message = updateIfExists ? 
                String.format("导入完成！新增：%d条，更新：%d条，失败：%d条", successCount[0], updateCount[0], failCount[0]) :
                String.format("导入完成！成功：%d条，失败：%d条", successCount[0], failCount[0]);
            
            result.put("success", true);
            result.put("message", message);
            result.put("successCount", successCount[0]);
            result.put("updateCount", updateCount[0]);
            result.put("totalSuccess", totalSuccess);
            result.put("failCount", failCount[0]);
            result.put("errors", errorMessages);

        } catch (IOException e) {
            log.error("读取Excel文件失败", e);
            result.put("success", false);
            result.put("message", "读取Excel文件失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("导入Excel文件失败", e);
            result.put("success", false);
            result.put("message", "导入失败：" + e.getMessage());
        }

        return result;
    }

    /**
     * 校验项目数据
     */
    private String validateProjectData(ProjectExcelDTO data, Integer rowNum) {
        // 项目编码（必填）
        if (data.getProjectCode() == null || data.getProjectCode().trim().isEmpty()) {
            return String.format("第%d行：项目编码不能为空", rowNum);
        }
        if (data.getProjectCode().length() > 64) {
            return String.format("第%d行：项目编码长度不能超过64个字符", rowNum);
        }

        // 项目名称（必填）
        if (data.getProjectName() == null || data.getProjectName().trim().isEmpty()) {
            return String.format("第%d行：项目名称不能为空", rowNum);
        }
        if (data.getProjectName().length() > 100) {
            return String.format("第%d行：项目名称长度不能超过100个字符", rowNum);
        }

        // 项目状态校验（1-5）
        if (data.getStatus() != null && (data.getStatus() < 1 || data.getStatus() > 5)) {
            return String.format("第%d行：项目状态值必须在1-5之间（1-未开始, 2-进行中, 3-已暂停, 4-已取消, 5-已完成）", rowNum);
        }

        // 优先级校验（1-5）
        if (data.getPriority() != null && (data.getPriority() < 1 || data.getPriority() > 5)) {
            return String.format("第%d行：优先级值必须在1-5之间（1-最高, 2-高, 3-中, 4-低, 5-最低）", rowNum);
        }

        // 项目类型校验（1-2）
        if (data.getProjectType() != null && (data.getProjectType() < 1 || data.getProjectType() > 2)) {
            return String.format("第%d行：项目类型值必须在1-2之间（1-整包项目, 2-人力项目）", rowNum);
        }

        // 项目进度校验（0-100）
        if (data.getProgress() != null && (data.getProgress() < 0 || data.getProgress() > 100)) {
            return String.format("第%d行：项目进度值必须在0-100之间", rowNum);
        }

        // 是否公开校验（0-1）
        if (data.getIsPublic() != null && (data.getIsPublic() < 0 || data.getIsPublic() > 1)) {
            return String.format("第%d行：是否公开值必须是0或1（0-否, 1-是）", rowNum);
        }

        // 日期格式校验（简单校验，支持YYYY-MM-DD格式）
        if (data.getStartDate() != null && !data.getStartDate().trim().isEmpty()) {
            if (!data.getStartDate().matches("\\d{4}-\\d{2}-\\d{2}")) {
                return String.format("第%d行：开始日期格式错误，应为YYYY-MM-DD格式（如：2024-01-01）", rowNum);
            }
        }
        if (data.getEndDate() != null && !data.getEndDate().trim().isEmpty()) {
            if (!data.getEndDate().matches("\\d{4}-\\d{2}-\\d{2}")) {
                return String.format("第%d行：结束日期格式错误，应为YYYY-MM-DD格式（如：2024-12-31）", rowNum);
            }
        }

        return null; // 校验通过
    }

    /**
     * 下载项目导入模板
     */
    @Override
    public byte[] downloadTemplate() {
        ByteArrayOutputStream outputStream = null;
        try {
            outputStream = new ByteArrayOutputStream();
            
            // 创建模板数据
            List<ProjectExcelDTO> templateData = new ArrayList<>();
            
            // 添加示例数据1
            ProjectExcelDTO example1 = new ProjectExcelDTO();
            example1.setProjectCode("PROJ-2024-001");
            example1.setProjectName("示例项目1");
            example1.setDescription("这是一个示例项目");
            example1.setStatus(2);
            example1.setPriority(1);
            example1.setStartDate("2024-01-01");
            example1.setEndDate("2024-12-31");
            example1.setBudget(new java.math.BigDecimal("1000000.00"));
            example1.setEstimatedCostRate(new java.math.BigDecimal("15.25"));
            example1.setProjectType(1);
            example1.setProgress(30);
            example1.setIsPublic(1);
            templateData.add(example1);

            // 添加示例数据2
            ProjectExcelDTO example2 = new ProjectExcelDTO();
            example2.setProjectCode("PROJ-2024-002");
            example2.setProjectName("示例项目2");
            example2.setDescription("这是另一个示例项目");
            example2.setStatus(1);
            example2.setPriority(3);
            example2.setStartDate("2024-06-01");
            example2.setEndDate("2024-12-31");
            example2.setBudget(new java.math.BigDecimal("500000.00"));
            example2.setEstimatedCostRate(new java.math.BigDecimal("12.50"));
            example2.setProjectType(2);
            example2.setProgress(0);
            example2.setIsPublic(0);
            templateData.add(example2);

            log.info("开始生成Excel模板，示例数据数量：{}", templateData.size());

            // 生成Excel文件
            EasyExcel.write(outputStream, ProjectExcelDTO.class)
                    .sheet("项目导入模板")
                    .doWrite(templateData);

            byte[] bytes = outputStream.toByteArray();
            log.info("Excel模板生成成功，文件大小：{} bytes", bytes.length);
            
            return bytes;

        } catch (Exception e) {
            log.error("生成模板文件失败", e);
            throw new RuntimeException("生成模板文件失败：" + e.getMessage(), e);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("关闭输出流失败", e);
                }
            }
        }
    }
}

